import canvasUtil from "./canvasUtil";
import mxgraph from "src/pages/mxgraph/graph/index";
import graphUtil from "pages/mxgraph/graphUtil";
import { GraphShapeUtil } from '@/pages/mxgraph/GraphShapeUtil';
const {
  mxConstants,
  mxEvent,
  mxEdgeHandler,
  mxUtils,
  mxRectangle,
  mxImageShape,
  mxElbowEdgeHandler,
  mxGraphHandler
} = mxgraph;

const mxEdgeHandlerChangePoints = mxEdgeHandler.prototype.changePoints;
/**
 *  拖拽连线控制点时触发此方法，同步变化到umlShape
 * @param {*} edge
 * @param {*} points
 * @param {*} clone
 */
mxEdgeHandler.prototype.changePoints = function (edge, points, clone) {
 
  //// message 拖动临时方案
  //// if (lifelineUtil.isMessageEdge(edge.typeName)) return;
  //// graphUtil.post('/graph/edge/updatePoints', { edgeShape: edge.umlShape, points: points });

  const result = mxEdgeHandlerChangePoints.apply(this, arguments);
  console.log('change points', edge);
  const mxGraphView = this.graph.getView();
  
  const edgeState = mxGraphView.getState(edge);
  const absolutePoints = [...edgeState.absolutePoints];
  const intersecPointIndex = mxGraphHandler.prototype.getIntersecPointIndex(absolutePoints);
  //// console.log('edgeState', edgeState, edgeState.absolutePoints);
  //// console.log('absolutePoints', points);
  console.log('absolutePoints', absolutePoints);
  console.log('intersecPointIndex', intersecPointIndex);
  if (intersecPointIndex < absolutePoints.length - 1) { //// 表示有线段相交
    //// console.log('resetedge');
    this.graph.resetEdge(edge);
    GraphShapeUtil.updateWaypoints(edge.umlShape, []);
  } else {
    GraphShapeUtil.updateWaypoints(edge.umlShape, points);
  }
  
  return result;
};

const mxEdgeHandlerCreateBends = mxEdgeHandler.prototype.createBends;

mxEdgeHandler.prototype.createBends = function()
{
  //// message不要创建bends
  if (this.state.style.bends === 0){
    return [];
  } else {
    return mxEdgeHandlerCreateBends.apply(this, arguments);
  }
};

const mxEdgeHandlerCreateVirtualBends = mxEdgeHandler.prototype.createVirtualBends;

mxEdgeHandler.prototype.createVirtualBends = function()
{
  //// message不要创建createVirtualBends
  if (this.state.style.bends === 0){
    return [];
  } else {
    return mxEdgeHandlerCreateVirtualBends.apply(this, arguments);
  }
};
/**
     * Updates the hint for the current operation.
     */
mxEdgeHandler.prototype.updateHint = function (me, point) {
  if (this.hint == null) {
    this.hint = canvasUtil.createHint();
    this.state.view.graph.container.appendChild(this.hint);
  }

  let t = this.graph.view.translate;
  let s = this.graph.view.scale;
  let x = this.roundLength(point.x / s - t.x);
  let y = this.roundLength(point.y / s - t.y);
  let unit = this.graph.view.unit;

  this.hint.innerHTML =
	canvasUtil.formatHintText(x, unit) + ", " + canvasUtil.formatHintText(y, unit);
  this.hint.style.visibility = "visible";

  if (this.isSource || this.isTarget) {
    if (
      this.constraintHandler.currentConstraint != null &&
          this.constraintHandler.currentFocus != null
    ) {
      let pt = this.constraintHandler.currentConstraint.point;
      this.hint.innerHTML =
            "[" +
            Math.round(pt.x * 100) +
            "%, " +
            Math.round(pt.y * 100) +
            "%]";
    } else if (this.marker.hasValidState()) {
      this.hint.style.visibility = "hidden";
    }
  }

  this.hint.style.left =
        Math.round(me.getGraphX() - this.hint.clientWidth / 2) + "px";
  this.hint.style.top =
        Math.max(me.getGraphY(), point.y) +
        this.state.view.graph.gridSize +
        "px";

  if (this.linkHint != null) {
    this.linkHint.style.display = "none";
  }
};

//// Disables adding waypoints if shift is pressed
mxEdgeHandler.prototype.isAddVirtualBendEvent = function (me) {
  return !mxEvent.isShiftDown(me.getEvent());
};

//// Disables custom handles if shift is pressed
mxEdgeHandler.prototype.isCustomHandleEvent = function (me) {
  return !mxEvent.isShiftDown(me.getEvent());
};

let startTime = new Date().getTime();
let timeOnTarget = 0;

let mxEdgeHandlerUpdatePreviewState =
      mxEdgeHandler.prototype.updatePreviewState;

mxEdgeHandler.prototype.updatePreviewState = function (
  edge,
  point,
  terminalState,
  me
) {
  mxEdgeHandlerUpdatePreviewState.apply(this, arguments);

  if (terminalState != this.currentTerminalState) {
    startTime = new Date().getTime();
    timeOnTarget = 0;
  } else {
    timeOnTarget = new Date().getTime() - startTime;
  }

  this.currentTerminalState = terminalState;
};

//// Timer-based outline connect
let mxEdgeHandlerIsOutlineConnectEvent =
      mxEdgeHandler.prototype.isOutlineConnectEvent;
/**
     * Hides link hint while moving cells.
     */
let edgeHandlerMouseMove = mxEdgeHandler.prototype.mouseMove;

mxEdgeHandler.prototype.mouseMove = function(sender, me)
{
  edgeHandlerMouseMove.apply(this, arguments);

  if (this.graph.graphHandler != null && this.graph.graphHandler.first != null &&
        this.linkHint != null && this.linkHint.style.display != 'none')
  {
    this.linkHint.style.display = 'none';
  }
};
//// let edgeHandlerMouseUp = mxEdgeHandler.prototype.mouseUp;

//// mxEdgeHandler.prototype.mouseUp = function(sender, me)
//// {
////   console.log('sender, me', sender, me);
////   return edgeHandlerMouseUp.apply(this, arguments);
//// };
mxEdgeHandler.prototype.isOutlineConnectEvent = function (me) {
  return (
    (this.currentTerminalState != null &&
          me.getState() == this.currentTerminalState &&
          timeOnTarget > 2000) ||
        ((this.currentTerminalState == null ||
          mxUtils.getValue(
            this.currentTerminalState.style,
            "outlineConnect",
            "1"
          ) != "0") &&
          mxEdgeHandlerIsOutlineConnectEvent.apply(this, arguments))
  );
};

//// Shows secondary handle for fixed connection points
mxEdgeHandler.prototype.createHandleShape = function (index, virtual) {
  let source = index != null && index == 0;
  let terminalState = this.state.getVisibleTerminalState(source);
  let c =
        index != null &&
        (index == 0 ||
          index >= this.state.absolutePoints.length - 1 ||
          (this.constructor == mxElbowEdgeHandler && index == 2))
          ? this.graph.getConnectionConstraint(
            this.state,
            terminalState,
            source
          )
          : null;
  let pt =
        c != null
          ? this.graph.getConnectionPoint(
            this.state.getVisibleTerminalState(source),
            c
          )
          : null;

  let img =
        pt != null
          ? this.fixedHandleImage
          : c != null && terminalState != null
            ? this.terminalHandleImage
            : this.handleImage;

  if (img != null) {
    let shape = new mxImageShape(
      new mxRectangle(0, 0, img.width, img.height),
      img.src
    );

    //// Allows HTML rendering of the images
    shape.preserveImageAspect = false;

    return shape;
  } else {
    let s = mxConstants.HANDLE_SIZE;
    if (this.preferHtml) {
      s -= 1;
    }

    return new mxRectangleShape(
      new mxRectangle(0, 0, s, s),
      mxConstants.HANDLE_FILLCOLOR,
      mxConstants.HANDLE_STROKECOLOR
    );
  }
};

let edgeHandlerInit = mxEdgeHandler.prototype.init;
mxEdgeHandler.prototype.init = function () {
  console.log('mxEdgeHandler init');
  edgeHandlerInit.apply(this, arguments);

  //// Disables connection points
  //// this.constraintHandler.isEnabled = mxUtils.bind(this, function () {
  ////   return this.state.view.graph.connectionHandler.isEnabled();
  //// });

  //// let update = mxUtils.bind(this, function () {
  ////   if (this.linkHint != null) {
  ////     this.linkHint.style.display =
  ////           this.graph.getSelectionCount() == 1 ? "" : "none";
  ////   }

  ////   if (this.labelShape != null) {
  ////     this.labelShape.node.style.display =
  ////           this.graph.isEnabled() &&
  ////           this.graph.getSelectionCount() < this.graph.graphHandler.maxCells
  ////             ? ""
  ////             : "none";
  ////   }
  //// });

  //// this.selectionHandler = mxUtils.bind(this, function (sender, evt) {
  ////   update();
  //// });

  //// this.graph
  ////   .getSelectionModel()
  ////   .addListener(mxEvent.CHANGE, this.selectionHandler);

  //// this.changeHandler = mxUtils.bind(this, function (sender, evt) {
  ////   this.updateLinkHint(
  ////     this.graph.getLinkForCell(this.state.cell),
  ////     this.graph.getLinksForState(this.state)
  ////   );
  ////   update();
  ////   this.redrawHandles();
  //// });

  //// this.graph.getModel().addListener(mxEvent.CHANGE, this.changeHandler);

  //// let link = this.graph.getLinkForCell(this.state.cell);
  //// let links = this.graph.getLinksForState(this.state);

  //// if (link != null || (links != null && links.length > 0)) {
  ////   this.updateLinkHint(link, links);
  ////   this.redrawHandles();
  //// }
};
//// mxEdgeHandler.prototype.updateLinkHint = function name(params) {
      
//// };

mxEdgeHandler.prototype.removeHint = function () {
  this.graph.graphHandler.removeHint.apply(this, arguments);
  //// mxGraphHandler.prototype.removeHint.apply(this, arguments);
      
  //// if (this.linkHint != null) {
  ////   this.linkHint.style.display = "";
  //// }
};

let edgeHandlerRedrawHandles = mxEdgeHandler.prototype.redrawHandles;
mxEdgeHandler.prototype.redrawHandles = function () {
  //// Workaround for special case where handler
  //// is reset before this which leads to a NPE
  if (this.marker != null) {
    edgeHandlerRedrawHandles.apply(this);

    if (this.state != null && this.linkHint != null) {
      let b = this.state;

      if (this.state.text != null && this.state.text.bounds != null) {
        b = new mxRectangle(b.x, b.y, b.width, b.height);
        b.add(this.state.text.bounds);
      }

      this.linkHint.style.left =
            Math.max(
              0,
              Math.round(b.x + (b.width - this.linkHint.clientWidth) / 2)
            ) + "px";
      this.linkHint.style.top =
            Math.round(b.y + b.height + 6 + this.state.view.graph.tolerance) +
            "px";
    }
  }
};

let edgeHandlerReset = mxEdgeHandler.prototype.reset;
mxEdgeHandler.prototype.reset = function () {
  edgeHandlerReset.apply(this, arguments);

  if (this.linkHint != null) {
    this.linkHint.style.visibility = "";
  }
};

let edgeHandlerDestroy = mxEdgeHandler.prototype.destroy;
mxEdgeHandler.prototype.destroy = function () {
  edgeHandlerDestroy.apply(this, arguments);

  if (this.linkHint != null) {
    this.linkHint.parentNode.removeChild(this.linkHint);
    this.linkHint = null;
  }

  if (this.selectionHandler != null) {
    this.graph.getSelectionModel().removeListener(this.selectionHandler);
    this.selectionHandler = null;
  }

  if (this.changeHandler != null) {
    this.graph.getModel().removeListener(this.changeHandler);
    this.changeHandler = null;
  }
};

mxEdgeHandler.prototype.handleImage = canvasUtil.vertexImg.mainHandle;
mxEdgeHandler.prototype.terminalHandleImage = canvasUtil.vertexImg.terminalHandle;
mxEdgeHandler.prototype.fixedHandleImage = canvasUtil.vertexImg.fixedHandle;
mxEdgeHandler.prototype.labelHandleImage = canvasUtil.vertexImg.secondaryHandle;

mxEdgeHandler.prototype.parentHighlightEnabled = true;
mxEdgeHandler.prototype.dblClickRemoveEnabled = true;
mxEdgeHandler.prototype.straightRemoveEnabled = true;
mxEdgeHandler.prototype.virtualBendsEnabled = true;
mxEdgeHandler.prototype.mergeRemoveEnabled = true;
mxEdgeHandler.prototype.manageLabelHandle = true;
mxEdgeHandler.prototype.outlineConnect = true;

mxEdgeHandler.prototype.snapToTerminals = true;

